Simplest formula to retrieve bg attribute?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
nesrocks
Posts: 430
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Simplest formula to retrieve bg attribute?

Post by nesrocks » Tue Mar 05, 2019 10:30 am

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: Select all

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?
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!

User avatar
pubby
Posts: 536
Joined: Thu Mar 31, 2016 11:15 am

Re: Simplest formula to retrieve bg attribute?

Post by pubby » Tue Mar 05, 2019 10:43 am

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.

User avatar
pubby
Posts: 536
Joined: Thu Mar 31, 2016 11:15 am

Re: Simplest formula to retrieve bg attribute?

Post by pubby » Tue Mar 05, 2019 10:49 am

If you have a tile x coord and y coord, here's how you would find the attribute byte:

Code: Select all

index = (x / 4) + (y / 128)*8
Then you'd look up the bits like this:

Code: Select all

bitmask = 0b11 << ((x & 0b10) + 4 - (y & 0b10) * 2)
I think. Haven't tested.

User avatar
nesrocks
Posts: 430
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Simplest formula to retrieve bg attribute?

Post by nesrocks » Tue Mar 05, 2019 10:54 am

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!
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!

User avatar
tokumaru
Posts: 11443
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Simplest formula to retrieve bg attribute?

Post by tokumaru » Tue Mar 05, 2019 1:25 pm

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: Select all

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: Select all

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.

User avatar
nesrocks
Posts: 430
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Simplest formula to retrieve bg attribute?

Post by nesrocks » Tue Mar 05, 2019 4:21 pm

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
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!

Post Reply