Page 1 of 1

Need a small refresher(PPU register relationships)

Posted: Sun Dec 24, 2017 12:55 pm
by zkip
Hi guys. It's been a while! Can someone refresh me on how $2006/$2007/$2005/$2000 relationships work again? I'm doing a simple thing that flashes a palette color in NMI, however it seems to corrupt the whole palette and part of the nametable somehow.

Code: Select all

NMI:
	PHA
	TXA
	PHA
	TYA
	PHA

	LDA $2002		;to acknowledge vblank
	INC NMITimer

	LDA NMITimer
	LSR A
	LSR A
	AND #$01
	TAX

	LDA #$3F
	STA $2006
	LDA #$01
	STA $2006

	LDA Palette,x
	STA $2007

	LDA #%10010000
	STA $2000

	LDA #$00
	STA $2005
	STA $2005

	PLA
	TAY
	PLA
	TAX
	PLA
	RTI

Palette: .db $04, $05
Does this code look correctly? It does to me. I'll spare you guys the whole code, but I will say that all other writes to $2007 are followed by the same writes to $2000 and $2005 as shown above.

Re: Need a small refresher(PPU register relationships)

Posted: Sun Dec 24, 2017 1:19 pm
by Quietust
That code by itself should work just fine; however, if you're doing more writes to $2007 during NMI, you need to make sure it takes less than 20 scanlines or you're going to spill into rendering time (which will cause the palette/nametable corruption you mentioned).

Re: Need a small refresher(PPU register relationships)

Posted: Sun Dec 24, 2017 1:53 pm
by dougeff
however it seems to corrupt the whole palette and part of the nametable somehow
it is probably some other code that is causing the problem. This code only does 1 write to 3f01.

Re: Need a small refresher(PPU register relationships)

Posted: Sun Dec 24, 2017 1:59 pm
by zkip
I'm not. That's the full NMI.

Also, the other code does basically....


Update edit: I fixed the problem, but if anyone has the time I'd love to hear an explanation as to exactly what happens here. I make the nametable and upload it before the screen is even turned on. The problem was because before doing this and also as you see in my code above I was setting the bit in $2000 to enable NMI on vblank. I fixed it by setting this bit off until just before I turn the screen on. Apparently the code in NMI that was being ran somehow glitched the writes to the nametable because vblank was happening in the middle of it and glitching the way $2006 works? It's really weird because I've never had code conflict in this manner.

Re: Need a small refresher(PPU register relationships)

Posted: Sun Dec 24, 2017 3:05 pm
by tokumaru
The NMI is an interrupt, meaning that when vblank starts, the CPU stops whatever it's doing and jumps to the NMI handler. If the code that's interrupted is working with VRAM, and the NMI handler also works with VRAM or uses registers that affect the VRAM address, the address will be incorrect when the NMI ends and the code that was running before resumes, so the following VRAM writes will certainly go to the wrong place.
I've never had code conflict in this manner.
These kinds of conflicts happen all the time. When you code an interrupt routine, you always have to think of the impact it can have on the rest of the program as it runs. We normally use flags to indicate what the NMI and IRQ handlers can or can't do depending on what's happening in the main program, to avoid these situations.