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:

Image

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. :oops: 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. :)