For some reason, in my program, an IRQ is happening. I'm not clear on why it's happening, as when i go to debug in fceuxdsp, it says that i'm in my program's main stalling loop. i hit "step into" over and over again, and it loops normally, hitting no breakpoints. of course, an IRQ is pending, so it keeps going to my IRQ handler, which currently consists of an RTI instruction. so, how do you turn off an IRQ anyways? SEI and CLI don't seem to stop it. it seems to be stopping my vblank routine from running (though i suppose it shouldn't as NMI takes precedence over IRQ, right?)
my code and .nes file are here:
I see you use a CLI to enable vblank NMI? SEI and CLI only affect IRQ, not NMI. If you're never going to use IRQs, the simplest solution would be a SEI at the start of your program (like you have right now), and never ever use CLI.
The cleaner solution would be to use SEI like above, and disable every IRQ 'generator', like the APU frame sequencer IRQ.
Another thing to watch out for is that SEI and CLI are reversed in meaning compared to x86.
The start of every program should execute SEI (to mask IRQ's), write $40 or $C0 to $4017 (to disable frame IRQ's), and write $00 to $4010 (to disable DMC IRQ's). If you're using a mapper that can generate IRQ's (such as the MMC3 and MMC5), be sure to perform whatever steps are required to disable IRQ's for the respective mapper.
These steps are common programming practice - never assume the state of anything. Until you explicitly disable all potential IRQ sources, you cannot safely assume that IRQ's won't occur. This advice is generic for all platforms, not just the NES.
OK. I've got an SEI at the beginning of my program and I never clear the interrupt bit. Only thing is, my NMI doesn't seem to be going off more than once. Right now, it just draws the first letter of text (it's supposed to draw a letter every frame). I set up a method that mimics what happens when vblank occurs, and when I force the PC to that method from the main loop it draws the next letters just fine. I guess when I do that it's actually outside of vblank, but for some reason fceuxdsp lets me do it. here's my vblank code:
Code:
frame'update:
lda mode ; if it's zero it means there is a new letter
cmp #$00 ; waiting to be placed in vram
beq gotoghost ; debug mode has shown that this actually gets set to 0
bne dont
gotoghost:
jsr ghostppu
dont:
rts
vblank: ; this is what $FFFA points to.
jsr frame'update
rti
irq:
rti
ghostppu:
lda $2001
and #%11100111
sta $2001 ; turn off ppu
lda vramlo
sta $2006
lda vramhi
sta $2006
lda nextletter
sta $2007
lda #$00
sta $2005
sta $2005
lda $2000
sta $2000
lda $2001
ora #%00011010
sta $2001
lda #$01
sta mode
rts
here's my main loop (callghostppu never gets called unless i manually set the PC):
Code:
mainloop:
ldx textindex
lda text, x
cmp #$FF ; i use this to note when my text is finished writing.
beq mainloopdone
sta nextletter
inc textindex
inc vramhi
lda #$00
sta mode
mainloopdone:
lda mode
cmp #$01
beq mainloop
jmp mainloopdone
callghostppu:
jsr frame'update
jmp mainloopdone
the updated code and .nes file can be seen here:
thanks in advance
Code:
ghostppu:
lda $2001
and #%11100111
sta $2001 ; turn off ppu
lda vramlo
sta $2006
lda vramhi
sta $2006
lda nextletter
sta $2007
lda #$00
sta $2005
sta $2005
lda $2000
sta $2000<----------------------------------
lda $2001
ora #%00011010
sta $2001
lda #$01
sta mode
rts
set a breakpoint at $C170 and you'll see that $00 is the last byte written to $2000, effectively turning NMI generation off.
i would also store the last values written to $2000/$2001 in variables rather then reading them back.
sweet! that totally worked!
now i just have to fix every other problem and code a million more things!
Like saving and restoring register(s) modified by your NMI handler. Having A changed at random points in your code is very hard to debug...
that's simple, though. having an NMI like this:
Code:
vblank:
pha
txa
pha
tya
pha
;NMI subroutines
pla
tay
pla
tax
pla
rti
will handle it, right?
By the way, can you tell me why
Code:
.segment zp
.org $0000
.space mode 1
.space vramhi 1
.space vramlo 1
.space textindex 1
.space nextletter 1
.space curr2000 1
.space curr2001 1
.advance $0010
produces a bunk rom but commenting out the .advance makes it work? i'm using p65 here. when i go to debug with that, its a rom that's basically all zeros (even in $C000), with a few FFs here and there. dunno why that ain't working.
Yes, that pushing/popping code is the simplest correct way to save and restore all registers properly. While on the subject, the status flags are automatically pushed on the stack by the processor before entering your interrupt handler, and RTI restores them from the stack, so a php...plp would be redundant and pointless.