Hi there,
I wrote a small game which should display a background (and do some more of course).
I've included a background made with Tile Layer Pro and name.exe and here's the code to show it:
ldx #$00
lda #$20 ; set the destination address in PPU memory
sta $2006 ; should be $2000
stx $2006
lda #low(bckgrnd)
sta addrLO ; into the variables so we can use indirect addressing.
lda #high(bckgrnd)
sta addrHI
ldx #4
ldy #0
bg_loop:
lda [addrLO],y
sta $2007
iny
bne bg_loop
inc addrHI
dex
bne bg_loop
Strangely the background isn't shown on the first line of the screen but somehow below like this:
line 30
line 31
line 32
line 01
What's the problem with my code?
The code you posted is fine.. the problem must be somewhere else.
Did you have the screen disabled when you wrote to VRAM? Did you write $0000 to $2006 when you're done (it's best to do that in the NMI routine).
How do I disable the screen? Do I have to do this before the posted code and after it write $0000 to $2006?
Disable the screen by writing zero to the $2001 register, re-enable it only when you're done writing to VRAM. Writing zero to $2006 should also be done while the screen is off, or during vblank (NMI).
Memblers wrote:
Did you write $0000 to $2006 when you're done (it's best to do that in the NMI routine)?
Actually, the proper thing to do is write to $2000 (bottom 2 bits, to set the 'origin' nametable) and $2005 twice (to set the horizontal and vertical scroll relative to said 'origin' nametable).
Thanks, that helped me a lot. Though I got the code to show the background from somewhere else, I don't know how to calculate the address of a background tile. How do I do that? (for changing parts of the BG to show player's score...)
On a 32 x 30 tilemap, assuming no scrolling:
(Y * 32) + X + NT base address ($2000, for example) = nametable address
Attribute tables are quite a bit trickier, heheh.
I assume you meant Y*32 there
Whoops, yeah. Good thing I can edit the post.
OK I tried it, but somehow I didn't get it right. Here's my code:
lda #3 ;should store tile 03h
sta $2000 ;at position 0,0
lda #4 ;tile 04h
sta $2008 ;at pos 8,0
lda #$13 ;tile 13h
sta $2256 ;at 0,8
lda #$14 ;and tile 14h
sta $2264 ;at 8,8
(the score's numbers are parted into four tiles to be 16x16px)
I forgot to turn the screen off and everytime that code was executed the screen became messed up, now it doesn't change at all!
Do I have an error in my address calculation or do I have to get the tiles from another address?
Oh, you need to use the I/O port to access video memory. Using the $2006 register for the address, and $2007 for data.
Like this:
(try alt+c for the code tags, BTW)
Code:
address = $2256
lda #>address
sta $2006
lda #<address
sta $2006
lda #4
sta $2007
I've managed to change tile 0,0 and 1,0 (address 2020 and 2021) but the other tiles are messed up on the screen.
I've calculated that tile 1,0 and 1,1's addresses should be 2052 and 2053.
For example (tile 1,1): 1*32+1+2020=2053. What's wrong?
Quote:
For example (tile 1,1): 1*32+1+2020=2053. What's wrong?
Looks like you're getting number bases confused.
The 32 is in decimal, and the 2020 is hex ($2020)
It's easier to to it all in one base:
y*$20 + x + $2020
(0, 0) = $2020
(0, 1) = $2021
(1, 0) = $2040
(1, 1) = $2041
Thanks, you saved my day (and robbed my sleep, it's nearly 2 AM but I had to code it) ^-^