Quantcast
Channel: nesdev.org
Viewing all articles
Browse latest Browse all 746

Synchronizing to NMI sans cartridge

$
0
0
I've been working on a technique to make NMIs usable for cartless programs, and I've been told that it would be a good idea to make a forum post for posterity.

The crux of the technique lies with the following code snippet, which configures the P register to seed open bus to produce an effective NMI vector which points to $2020—a mirror of write only PPUCTRL—and stuffs PPU open bus with the BCC $90 opcode, which branches back to a mirror of RAM address $07B2 when executed. A big thanks to lidnariq, who pointed out that my original code which only wrote to PPUCTRL once would be unstable on some consoles due to fast PPU open bus decay.

Code:

wait_for_nmi:; NMIs are left disabled for most of the frame, only being enabled when we're prepared to receive an interruptLDY #$90; Opcode for BCC, operand meaning a branch of -112 bytes, and PPUCTRL value meaning enable NMIs; Clear all bits in P Register. Keeping in mind that bit 5 is always set when pushed to the stack, we get a result of P = $20, and an effective NMI vector of $2020; Optimized by Sylvie on discordLDA #$00PHAPLP; Clear vblank flag without affecting CPU flags, to minimize the chances of initiating an NMI partway through vblankNOP PPUSTATUS; Enable NMIs, stuff PPU open bus with opcode for BCC. At this point it is safe to be interrupted:STY PPUCTRL; Sit in a loop, refreshing PPU open bus until NMI comesJMP :-
Then, the beginning of your NMI handler would look something like this:

Code:

.org$07B2nmi:; Clear stack of interrupt return state, tidying as we go so as to not break resetsLDA #$00LDX #$03:PLPPHAPLPDEXBNE :-; Disable further NMIsSTA PPUCTRL; Any other vblank related tasks can go here
I've put together a very rough demo showcasing what can be done with the technique, a simple breakout clone that uses PPUMASK to mimic background pixels. I've tested it on my NES and it seems to work perfectly (other than a few paddle bugs :P), but please let me know if anyone finds that it's inconsistent. Notably, I'm using a sprite zero hit to refine my timings, which I've heard may not be perfectly reliable even when seeding nametable RAM to match open bus.I've also attached the (cobbled together) source code; I want to clean it up more, but I've been putting this post off for too long as it is, and the relevant parts should be well enough commented.

Statistics: Posted by Not_Kieran_F — Sat Dec 28, 2024 4:43 am — Replies 0 — Views 57



Viewing all articles
Browse latest Browse all 746

Trending Articles