Simplest formula to retrieve bg attribute?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Simplest formula to retrieve bg attribute?
by on (#235608)
In my program I'm emulating the nametables by creating a single texture that is all four nametables (512x480 px). It is working right now with all tiles having attribute 0.
Now I'm having trouble with coming up with a formula to get and apply the correct tile attributes.

The wiki has this but I don't know what to make of it. I see the << are bit shifts, but other than that I have no idea what is going on.
Code:
value = (bottomright << 6) | (bottomleft << 4) | (topright << 2) | (topleft << 0)

edit: ah ok, I guess this is what is used to generate the attribute table. Not quite what I want. Maybe reversing this solves my problem #2?

So, what I can't do in a simple formula is, knowing a tile's coordinates:
1 - know which byte to read.
2 - get the attribute for it from that byte.

I've managed to get it done by creating 64 case switches, but needless to say that is incredibly slow.

I'm programming in GML but I guess a solution in any language would be all I need.

edit2: Is a lookup table the answer to problem #1?
Re: Simplest formula to retrieve bg attribute?
by on (#235609)
I'm a little confused. If you're not doing NES programming, it wouldn't make sense to use the NES format which packs 4 attribute values into 1 byte. Instead you'd store things unpacked as a 16x16 array.

Regardless, here's a good page on attributes: https://wiki.nesdev.com/w/index.php/PPU ... ute_tables

1 attribute byte is a 32x32 pixels area. There are 64 attribute bytes in total. They start at the upper-left corner and are in row-major order.

Each attribute byte has four 16x16 quadrants. That code you've pasted explains how the 2-bit palette of each quadrant is stored in the attribute byte.
Re: Simplest formula to retrieve bg attribute?
by on (#235610)
If you have a tile x coord and y coord, here's how you would find the attribute byte:

Code:
index = (x / 4) + (y / 128)*8


Then you'd look up the bits like this:

Code:
bitmask = 0b11 << ((x & 0b10) + 4 - (y & 0b10) * 2)


I think. Haven't tested.
Re: Simplest formula to retrieve bg attribute?
by on (#235612)
I'm simulating the PPU memory in a buffer (the user can load a CHR, a NAM and a PAL into the program). Then I'm reading from all that to get the nametable and its attributes, to generate a texture for displaying on the screen, with the correct scroll set by the user. My thinking is that I want to work with a replica of NES' PPU memory so I can keep it all realistic.

So I have no trouble setting the attribute to the nametable, or even reading it really, since I did with a long case switch. But reading is slow. The user will be able to modify the nametable and it has to be updated in real time.
I was wondering if there was a general bitwise operated formula to get and convert a tile's corresponding attribute from the attribute table. I guess it's best to just have a precalculated lookup table for which bytes from the attribute table correspond to which tile coordinates.

edit: or try your new post. I'll try it!
Re: Simplest formula to retrieve bg attribute?
by on (#235620)
Instead of applying formulas blindly (like physics teachers often have us do in school), it's better to think of the work you have to do. Name table addresses have the following format:

Code:
0010NNYY YYYXXXXX (NT address)
NN: name table;
YYYYY: tile Y;
XXXXX: tile X;

But in order to access attribute table data, the information above has to be arranged differently:

Code:
0010NN11 11YYYXXX (AT address)
NN: name table;
YYY: top 3 bits of tile Y;
XXX: top 3 bits of tile X;

That's enough to access the byte that contains the attributes for the 32x32-pixel region where your tile of interest is, but since that region contains 4 sets of attributes, you need to use bit 1 of the X and Y coordinates (which you previously discarded when calculating the byte's address) to know which set of attribute bits to use. You can then use the quadrant index (%00 to %11) in a small switch statement or look-up the bit masks and shift amounts to reach the bits of interest.

Bit 0 of the X and Y coordinates is actually discarded for good, since attributes are applied to 16x16-pixel areas, not to individual tiles, so the specific tile within the 16x16-pixel area doesn't matter.
Re: Simplest formula to retrieve bg attribute?
by on (#235625)
Thanks, guys, I think I got it working now. Though it still seems a bit slow for real time rendering of pyxel by pixel, so I'll have to find some way to optimize when the time comes. Maybe only update the tile the user is modifying and leave the rest as a pre-rendered texture.

https://twitter.com/bitinkstudios/statu ... 8055005184