I haven't written 65XX ASM in about 10 years and I'm pretty new to NES coding, so i'm looking for some clarification on writing tiles to the background. I'm cool with the foreground sprites, those are working great.
I'm missing something here and a lot of tutorials seem to gloss over backgrounds. What i can't figure out is how to set exactly where i want the tiles to go.
Let's say my active name table is $2000, and i'm trying to write the letter "A" to the background. My chr has the alphabet in the correct ascii locations (A = 65).
So if i want to write my "A" to the upper left corner of the screen:
write $20 to $2006
write $00 to $2006
write $67 to $2007
Am I right? Because i can't get that to work at all.
If that's the case, is there an easy way to figure out what part of the name table matches what hex value?
Well, if you're using the ASCII codes, $41 is the hex for 65.
Secondly, $2000 is the top left corner and, depending on the emulator, may not show up as a lot of them like to configure it so the top 2 or 3 rows get clipped. Try turning on PAL emulation if you're using FCE Ultra.
But a basic way to do what you want is:
LDA #$20
STA $2006
LDA #$00
STA $2006
LDA #$41
STA $2007
Is there some sort of counter i have to reset when i'm writing to $2006 or $2007?
I'm using this code in 2 different parts of the program:
LDA #$22
STA $2006
LDA #$65
STA $2006
LDA #$41
STA $2007
And it's showing up in 2 different parts of the screen. One is showing up in the top half, the other is showing up in the bottom half. I know $2007 has some kind of counter, so maybe i need to reset that? I'm not sure where that counter is, or how to reset it.
Welcome to NESDev!
When you directly write to $2006, no counter is affected. When you write to $2007, it will either move on to the current address + 1 or the current address + 32, depending on the value of $2000 (crap, it might be $2001). NESTech will say which one it is.
Anyways, if you are directly writing to $2006 before each $2007 write, the data should be stored exactly where you are pointing it to. Make sure that you are writing to the PPU only during Vblank, or with rendering disabled. This is accomplished by writing $00 to $2001. Then before enabling the screen again, make sure you're setting the scroll registers properly. So this:
lda #$00
sta $2001
lda #$22
sta $2006
lda #$C9
sta $2006
lda #$67
sta $2007
lda #$00
sta $2005
sta $2005
lda #$1E
sta $2001
Would work, assuming you are aligning the scroll to pixel 0, 0 on name table $2000. Hope this helps.
EDIT: If this is on a frame-to-frame basis, you'll want to perform this at the beginning of the NMI during natural Vblank, which lasts 2270 cycles. That way, you won't have to disable rendering to write to the background.
Awesome, thanks!
Hehe, typo on the insertion into $2007. I was inserting a blank tile.
Thanks for the help. I'm going to stick around, i actually like working on the NES.
Well technically, writing to $2006 "increments" a one-bit internal counter that allows the PPU to tell whether you're writing the low or high byte of the VRAM address. So this counter can get out-of-sync with your code. Reading $2002 resets this, a good idea if things aren't working and you aren't sure of this even/odd flag's state.
I'm still one step away from "getting it". I'm drawing the background fine, but now i can't clear it.
This is what i'm trying as a clear routine. I'm trying to set $2000 to all zeroes:
clear:
lda #$20 ; clear vram
sta $2006
lda #$00
sta $2006
ldy #$00
lda #$00
sta $2007
iny
bne clear
I'm sure there's a better way to clear it (especially since it doesn't work). I guess i'm assuming that when you overflow A it should reset to 0...
Okay, there are a couple major problems with this loop:
clear:
lda #$20 ; clear vram
sta $2006
lda #$00
sta $2006
ldy #$00
lda #$00
sta $2007
iny
bne clear
First you should know this loop is infinite; you will never leave this loop. Y is being loaded to #$00 constantly, and increased to 1, branching to "clear" every time. So take ldy #$00 out of the loop.
Secondly, you are setting $2006 to point to $2000 every time the loop is executed. Even though writing to $2007 will add 1 to $2006, when you write values directly to $2006, it is forced to point to that location. So it is adding 1 to $2006, forcing it to point to $2000, adding 1, pointing to $2000, etc.
And finally, this loop would only clear 256 tiles if it were set up properly. This is probably the loop you'll want to use; it clears attribute data too:
lda #$20
sta $2006
ldx #4
ldy #0
tya
sta $2006
-
sta $2007
iny
bne -
dex
bne -
This will start it pointing to $2000, then every write to $2007 will make $2006 point to the next entry in the name table. It will increase Y 256 times, wrapping to 0, then decreasing X by 1 and repeating the process until X is 0. Since X is 4, it will clear 256 consecutive bytes of the name table 4 times, thus resulting in all 1024 (256 * 4) bytes being cleared.
Alternatively, you can do this after setting $2006 to #$20 and #$00 (or whatever nametable you are wanting to):
Code:
ldx #$00
clear:
sta $2007
sta $2007
sta $2007
sta $2007
dex
bne clear
Since $2007 increments itself, you can do this. This way you can do the loop the way you want to, 256 times. I believe I learned this from blargg's tutorial programs, but I'm not 100% sure.
Hey, you're right Roth! I was thinking about the loop I usually use to copy a raw .NAM file to the name table, which you use indirect Y addressing for, and that's why you do the iny, dex thing. Your loop would be much faster.
Thank you very much for the help!