How to change a tile Attributes (subpal) at a specific position?

dale_coop

Moderator
Staff member
Ok, here's my "problem":
I have a tile at a specific position (tileX, tileY).
I would like to change its attributes, more precisely, I want to change its subpalette (to subPal 4)... by code (want to use it in a collision tile script or a AIAction/EndAction script or timer...)

I spent the day, diggin' into the code... but haven't got any results.
Does someone know how to do that and would share a piece of code, a macro or a subroutine to do that?
Thank you in advance
 

jorotroid

Member
Ugh, it's been so long since I have posted. I forgot that the forum sometimes logs you out if you don't do change pages for a while. Going to try typing this up again.

I have some code I wrote back in the 4.0.11 days that I think should still work (though it might not be as efficient as it could be). I'll add some comments to try to explain what is going on.

First have the x and y pixel coordinates loaded into tileX and tileY. Then have the value of the palette you want to change to loaded and repeated over a single byte. So if you want to change to palette 0 load #%00000000, 1 load #%01010101, 2 load #%10101010, and for 3 load #%11111111.

Code:
	STA temp2				; We're storing the palette value for use later
	
	LDA tileX				; We need to convert our X and Y coordinates to the corresponding 
	LSR					; value for the lo byte of the attribute address. Columns have ending 
	LSR					; value of 0-7 on odd rows, even have 8-F. Every 2 rows share the hi nibble 
	LSR					; going from C to F. So for example the lo byte of the attribute address of
	LSR					; the 3rd row, 5th column would $D4. Because row 1 is C, row 2 is C, and
	LSR					; row 3 is D. This is an odd row, so the column value would be 0-7, so the 
	CLC					; 5th column would give you a value of 4. To get these values we just do
	ADC #$C0				; some bit shifting and some math.
	STA temp
    
	LDA tileY				; Now we get the Y component of the coordinate
	AND #$E0
	LSR
	LSR
	CLC
	ADC temp				; Now the X and Y components get merged to get us the final lo byte value
	STA updateNT_fire_att_lo
    
	LDA #$23				; The hi byte depends on which nametable you are targeting. The upper 
	STA updateNT_fire_att_hi		; left is #$23, upper right is #$27, lower left is #$2B, and lower right is #$2F
    
    
; This next section of code is for determining which of the 4 metatiles available at this attribute address we 
; are updating. It goes by the following pattern:
; 7654 3210
; |||| ||++- Color bits 3-2 for top left quadrant of this byte
; |||| ++--- Color bits 3-2 for top right quadrant of this byte
; ||++------ Color bits 3-2 for bottom left quadrant of this byte
; ++-------- Color bits 3-2 for bottom right quadrant of this byte

	LDA tileX						
	AND #%00010000				
	BEQ setLeftAttributes
        
        LDA tileY
        AND #%00010000
        BEQ setTopRightAttribute
setBottomRightAttribute:
        LDA temp2
        AND #%11000000
        STA updateNT_att
        LDA #%00111111
        STA updateNT_attMask
        JMP doneWithTileAttChange
setTopRightAttribute:
        LDA temp2
        AND #%00001100
        STA updateNT_att
        LDA #%11110011
        STA updateNT_attMask
        JMP doneWithTileAttChange

        
setLeftAttributes:
        LDA tileY
        AND #%00010000
        BEQ setBottonLeftAttribute
setTopLeftAttribute:
        LDA temp2
        AND #%00110000
        STA updateNT_att
        LDA #%11001111
        STA updateNT_attMask
        JMP doneWithTileAttChange
setBottonLeftAttribute:
        LDA temp2
        AND #%00000011
        STA updateNT_att
        LDA #%11111100
        STA updateNT_attMask
        JMP doneWithTileAttChange
        
doneWithTileAttChange:

	LDA #$01			; We're done getting and setting the values we needed, now we just need to
	STA UpdateAtt			; set this flag so an attribute update will occur during the next NMI


I hope that works or at least sets you in the right direction. Let me know if you have any troubles. Also be sure to look at the NESdev page on PPU attribute tables if you haven't already.
 

dale_coop

Moderator
Staff member
Thank you Joro, as usual <3
I will try testing and working with your code, tonight.
See you later
 

dale_coop

Moderator
Staff member
jorotroid said:
I hope that works or at least sets you in the right direction. Let me know if you have any troubles. Also be sure to look at the NESdev page on PPU attribute tables if you haven't already.

Did some tests last night, without any success. Pretty sure, I am missing something... easy.
For that test, I used the scrolling platform module... and simple test, trying to change the sub palette of one particular tile on the screen (when colliding, for example...)
 

jorotroid

Member
Ok either I gave you the wrong variables, or I was using the different variables for contexts that I no longer remember. So in my previous code replace updateNT_fire_att_lo, updateNT_fire_att_hi, and updateNT_att with updateNT_att_fire_Address_lo, updateNT_att_fire_Address_hi, and updateNT_fire_Att, respectively. That should get you your desired effect. I didn't test this code with scrolling, so there is a chance it might interfere with scroll updates of vise versa.
 

jorotroid

Member
dale_coop said:
Oh, yes...It works! Thank you, Joro, it will help me a lot.
You are my Yoda <3

Hahaha! Welcome, are you.

Glad it worked out, and I look forward to seeing what you are coming up with.
 

dale_coop

Moderator
Staff member
Oh, I can share...
It's nothing impressive, it's just small project I work on, a (commissionned) small game for a graffiti street artist:

GRAF.gif

Basically you paint tiles... but of course, the artist want specific colors on the graffiti ;)
 

Jaboc1234

New member
dale_coop said:
Oh, I can share...
It's nothing impressive, it's just small project I work on, a (commissionned) small game for a graffiti street artist:

GRAF.gif

Basically you paint tiles... but of course, the artist want specific colors on the graffiti ;)


And here i am making a simple Legend Of Zelda clone! lol Good work!
 

mouse spirit

Well-known member
Thank you joro. This helped me turn lava into ice and make and apply my first macro. Thanks alot.

And dale_coop, that is awesome.
 

marp

Member
This script worked excellent in 4.1 but I have a hard time "converting" it to work with the new 4.5 screen drawing routines. Trying to get my head around the scrollUpdateRam way of doing it. Anyone else tried this and had any success playing with this?

How did the graffiti game turn out Dale? Looking fun. =D
 
Top Bottom