Page 1 of 1
Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 7:29 am
by roedesh
I have some trouble updating a specific background tile, specifically finding the address to write the new tile to.
My game contains 8px grid movement, so my x and y values already are 8px units (I've read somewhere that this is necessary).
What I would like to know is how to calculate the new address.
So basically, something like this:
Code: Select all
UpdateTiles:
LDA p1y
ASL
ASL
ASL
ASL
ASL ; player Y-coord times 32
STA tile_y
LDA p1x
STA tile_x ; player X-coord
; calculate high and low address with x and y
LDA $2006
LDA addr_lo
STA $2006
LDA addr_hi
STA $2006
LDA #$39
STA $2007
Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 7:43 am
by pubby
You have to do 16 bit shifts using ROL, not 8 bit ones, otherwise you throw away bits.
Code should look something like this:
Code: Select all
lda #0
sta addr+1
lda p1y
asl
rol addr+1
asl
rol addr+1
asl
rol addr+1
asl
rol addr+1
asl
rol addr+1
adc p1x
sta addr+0
lda addr+1
adc #$20
sta $2006
lda addr+0
sta $2006
('addr' is a 2-byte zeropage variable)
Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 8:59 am
by roedesh
Thanks, that works. I can update the tiles now, but when I do so it causes some glitchy stuff to happen:

Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 9:23 am
by pubby
Try putting this after the updates:
Code: Select all
lda #0
sta $2006
sta $2006
sta $2005
sta $2005
Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 10:52 am
by roedesh
That did the trick! If I may ask, what exactly does that piece of code do?
Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 11:21 am
by pubby
Writing to $2006 (such as when pushing nametable data) affects the scroll register. The code above sets the scroll back to 0,0 by writing 0 to $2005.
Re: Get address from background tile at x,y in ASM
Posted: Sun Jul 22, 2018 11:35 am
by tepples
In fact, provided you're still in vblank, you don't even need to write $00 to $2006 to "clear" the VRAM address. You just have to set the scroll position with two writes to $2005 and one write to $2000 (to select the starting nametable).
Code: Select all
; Definitions
PPUCTRL = $2000
NT_2000 = $00
NT_2400 = $01
NT_2800 = $02
NT_2C00 = $03
VRAM_DOWN = $04
OBJ_0000 = $00
OBJ_1000 = $08
OBJ_8X16 = $20
BG_0000 = $00
BG_1000 = $10
VBLANK_NMI = $80
PPUSCROLL = $2005
; The writes in question
lda #VBLANK_NMI|OBJ_1000|BG_0000|NT_2000
sta PPUCTRL
lda #0
sta PPUSCROLL
sta PPUSCROLL
Re: Get address from background tile at x,y in ASM
Posted: Wed Aug 01, 2018 4:58 pm
by unregistered
pubby wrote:You have to do 16 bit shifts using ROL, not 8 bit ones, otherwise you throw away bits.
Maybe would help easier if it had said:
You have to do 16-bit shifts using ROL, not 8-bit ones, otherwise you throw away bits.
I was confused because I was thinking that pubby was talking about increasing the number of shifts.

But, after seeing that pubby's code uses the exact same number of shifts, ASLs, it made more sense eventually.
pubby wrote:('addr' is a 2-byte zeropage variable)
Further explaination: 2-byte is 16-bits. Each ASL does shift bit7 into the carry. Each ROL does rotate the carry into bit0. So it is transferring the bits you were throwing away into addr+1 and so pubby's code is correctly using 16-bit bit-shifting.
p.s. Each byte's eight bits are numbered
7 6 5 4 3 2 1 0.
