I guess this is basically my questions thread now
Moderator: Moderators
-
Jeff Garneau
- Posts: 6
- Joined: Wed Feb 21, 2007 1:45 pm
I guess this is basically my questions thread now
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:
my code and .nes file are here:
Last edited by Jeff Garneau on Thu Jul 24, 2008 5:12 pm, edited 2 times in total.
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.
The cleaner solution would be to use SEI like above, and disable every IRQ 'generator', like the APU frame sequencer IRQ.
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.
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.
-
Jeff Garneau
- Posts: 6
- Joined: Wed Feb 21, 2007 1:45 pm
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:
here's my main loop (callghostppu never gets called unless i manually set the PC):
the updated code and .nes file can be seen here:
thanks in advance
Code: Select all
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
Code: Select all
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
thanks in advance
Last edited by Jeff Garneau on Thu Jul 24, 2008 5:12 pm, edited 1 time in total.
- never-obsolete
- Posts: 411
- Joined: Wed Sep 07, 2005 9:55 am
- Location: Phoenix, AZ
- Contact:
Code: Select all
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
i would also store the last values written to $2000/$2001 in variables rather then reading them back.
-
Jeff Garneau
- Posts: 6
- Joined: Wed Feb 21, 2007 1:45 pm
-
Jeff Garneau
- Posts: 6
- Joined: Wed Feb 21, 2007 1:45 pm
that's simple, though. having an NMI like this:
will handle it, right?
By the way, can you tell me why
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.
Code: Select all
vblank:
pha
txa
pha
tya
pha
;NMI subroutines
pla
tay
pla
tax
pla
rti
By the way, can you tell me why
Code: Select all
.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
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.