It is currently Wed May 22, 2019 3:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Tue Mar 05, 2019 10:30 am 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 405
Location: Rio de Janeiro - Brazil
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?

_________________
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!


Top
 Profile  
 
PostPosted: Tue Mar 05, 2019 10:43 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
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.


Top
 Profile  
 
PostPosted: Tue Mar 05, 2019 10:49 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
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.


Top
 Profile  
 
PostPosted: Tue Mar 05, 2019 10:54 am 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 405
Location: Rio de Janeiro - Brazil
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!


Top
 Profile  
 
PostPosted: Tue Mar 05, 2019 1:25 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11347
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Tue Mar 05, 2019 4:21 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 405
Location: Rio de Janeiro - Brazil
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!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group