puppydrum64 wrote: ↑Mon May 03, 2021 1:22 pm
I'm not sure if I understand how this works, but after every frame NMI should occur and the program counter performs the following command: JMP ($FFFA), then it executes that code until it hits "RTI" and then returns back to where it was prior to the interrupt. That being said, I don't know why it's not happening here. I ran this ROM in Mesen and set a breakpoint for RTI but it never happens, nor does my custom variable "vblanked" ever change.
Code: Select all
org $BFF0
db "NES",$1a ;ID
db $01 ;Rom pages (16k each)
db $0 ;CHR-ROM pages
db %01000010 ;mmmmFTBM mmmm = mapper no bottom 4 bits , Four screen vram layout, Trainer at &7000, Battery ram at &6000, Mirror (0=horiz, 1=vert)
db %00000000 ;mmmm--PV mapper (top 4 bits... Pc10 arcade, Vs unisystem )
db 0 ;Ram pages
db 0,0,0,0,0,0,0
;We selected Mapper 4 - it has 8k VRAM , 8K Sram and 128k rom
vblanked equ $7F ;Zero page address of Vblank count
nmihandler: ;This procuedure runs after each frame (See footer.asm)
php
inc vblanked ;Alter Vblank Zero page entry
plp
rti
irqhandler:
rti ;Do nothing
NES_main:
sei ;Interrupts on
cld ;Clear Decimal flag
ldx #$ff ;Set up stack
txs
lda #%10000000 ;Turn on extra ram at $6000-%7FFF
sta $A001
wait_nmi:
lda vblanked
notYet:
cmp vblanked
beq notYet
rts
infloop:
jsr wait_nmi
jmp infloop
org $FFFA
dw nmihandler ;FFFA - Interrupt handler
dw NES_main ;FFFC - Entry point
dw irqhandler ;FFFE - IRQ Handler
There are multiple problems with your code:
1. The PPU does not generate NMIs unless you tell it to do so by writing to $2001 with the high order bit (#$80) set.
1a. In order to enable NMIs, you'll also need to wait for the PPU to warm up - most emulators won't punish you for missing this, but on a real NES any writes to $2000/$2001/$2005/$2006 will have no effect until at least ~29658 CPU cycles have elapsed, and most games handle this by polling register $2002 to wait for two frames.
2. Your program flow is incorrect - execution begins at NES_main, flows into the "wait_nmi" routine, and then hits an RTS instruction which will
underflow the stack and cause your program to crash.
3. I don't believe the MMC3 is guaranteed to map the 2nd-last 8KB bank at $C000-$DFFF on powerup - if the PRG ROM Bank Mode happens to initialize to 1 (such that $C000-$DFFF is swappable via bank register R6), your program will probably crash on startup.