Indirect referencing a banked location in CA65

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Indirect referencing a banked location in CA65
by on (#215910)
Can anyone provide a code example of how you would reference a 3 byte (i.e. bank and then 16k address) location on the SNES using a pointer in CA65 ASM? Is this something that is commonly done or am I missing a trick?

The intention is to use nested lookup tables for scenes, palettes, and the suchlike. I can currently only get an indirect reference working for a single byte and a word however, which would seem to limit me to 16ks worth of addresses.

Where am I going wrong?

The lookup is like this:

Code:
hello_palettes:
.word palette_1, palette_2


pointing to palettes like this:
Code:
palette_0:

.byte %00000011, %11111111
.byte %00011100, %00011111
.byte %11111111, %00000011
.byte %11110011, %01100011


palette_2:

.byte %00000011, %11111111
.byte %00000011, %11100000
.byte %01111111, %11111111
.byte %00000000, %00010100


and the look up routine looks like this:

Code:
.pushseg

.ZEROPAGE

palette_pointer:
.res 2

.popseg

.proc load_palette
sta PPU_CG_ADDR
   
lda #2
asl a
;for 3 byte addresses, another asl a would be here
tax
lda hello_palettes,x   
sta palette_pointer
lda hello_palettes+1,x
sta palette_pointer +1
lda hello_palettes+ 2,x
sta palette_pointer + 2

ldy #0
@loop:
lda (palette_pointer),y
sta PPU_CG_DATA
iny
cpy #8
bmi @loop
rts
.endproc ;end of load_palette


If I increase the pointer reserve to 3, put in another asl, and change the lookup table to a faraddr, it doesn't seem to work.

I've been using bsnes debugger and it looks like the 65816 doesn't load a 3 byte address, only a two byte one.

What am I doing wrong? Is this the wrong way to address storage across banks?
Re: Indirect referencing a banked location in CA65
by on (#215912)
Have you tried using square brackets lda [dd],Y instead of round ones lda (dd),Y when using 24-bit addresses on direct page?
Re: Indirect referencing a banked location in CA65
by on (#215917)
That was it! Genius, thank you tepples! I was reading the docs as well, I don't know why that didn't click.

For anyone else trying to use three byte addresses, here's the working routine (this is for a 16 colour palette):

Code:

.pushseg

.ZEROPAGE

palette_pointer:
.res 3

;this is used as a temp register
zp_reg_0:
.res 1

.popseg


.proc load_palette
sta PPU_CG_ADDR
   
lda #2  ;this is your palette number in the table, so you'll actually want to fill a register with this on entry in to the routine
sta zp_reg_0
asl a
clc   
adc zp_reg_0
tax
lda hello_palettes,x
   
sta palette_pointer
lda hello_palettes+1,x
sta palette_pointer +1
lda hello_palettes+ 2,x
sta palette_pointer + 2
   
ldy #0
@loop:
lda [palette_pointer],y
sta PPU_CG_DATA
iny
cpy #32  ;16 colours
bmi @loop
rts
.endproc ;end of load_palette