I guess this is basically my questions thread now

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
Jeff Garneau
Posts: 6
Joined: Wed Feb 21, 2007 1:45 pm

I guess this is basically my questions thread now

Post by Jeff Garneau »

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:
Last edited by Jeff Garneau on Thu Jul 24, 2008 5:12 pm, edited 2 times in total.
User avatar
hap
Posts: 355
Joined: Thu Mar 24, 2005 3:17 pm
Contact:

Post by hap »

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.
tepples
Posts: 22603
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Another thing to watch out for is that SEI and CLI are reversed in meaning compared to x86.
dvdmth
Posts: 354
Joined: Wed Mar 22, 2006 8:00 am

Post by dvdmth »

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.
Jeff Garneau
Posts: 6
Joined: Wed Feb 21, 2007 1:45 pm

Post by Jeff Garneau »

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: 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
here's my main loop (callghostppu never gets called unless i manually set the PC):

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
the updated code and .nes file can be seen here:

thanks in advance
Last edited by Jeff Garneau on Thu Jul 24, 2008 5:12 pm, edited 1 time in total.
User avatar
never-obsolete
Posts: 411
Joined: Wed Sep 07, 2005 9:55 am
Location: Phoenix, AZ
Contact:

Post by never-obsolete »

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
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.
. That's just like, your opinion, man .
Jeff Garneau
Posts: 6
Joined: Wed Feb 21, 2007 1:45 pm

Post by Jeff Garneau »

sweet! that totally worked!

now i just have to fix every other problem and code a million more things!
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

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...
Jeff Garneau
Posts: 6
Joined: Wed Feb 21, 2007 1:45 pm

Post by Jeff Garneau »

that's simple, though. having an NMI like this:

Code: Select all

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: 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
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.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

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.
Post Reply