refresher with setting bit(s) within palette attribute

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
infidelity
Posts: 340
Joined: Fri Mar 01, 2013 4:46 am

refresher with setting bit(s) within palette attribute

Post by infidelity » Sun Aug 21, 2016 3:31 pm

Working on a new project from the ground up, coming along nicely, but i'm at a point where I have to alter the attribute table when certain sections of the bg need to be changed to a specific palette.

I already know how to set a 16x16 grid to whichever palette Id like, the problem I'm having, is how do I set the bit within the attribute table?

What I have going on, is depending on the specific position, i'll load up a table that contains values meant as bits. For instance, i'll load up a byte as the value (30). What I need to do from here, is use that value 30 as (..21 ....) and alter the specific address within the attribute table.

I know I cant simply take that 30 and store it to the attribute address, that's no good.

I tried doing as much on my own from memory as I could, but bits have reared its ugly self again, heh. Thanks for reading, hope I can get this situated fast. :-D

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

Re: refresher with setting bit(s) within palette attribute

Post by tokumaru » Sun Aug 21, 2016 3:46 pm

The smallest data unit that the CPU can manipulate is a byte, meaning there's no way to directly load or store less than 8 bits at once. For this reason, you need to use some bitwise operation tricks to manipulate only the necessary bits inside a byte.

Typically, when you need to change only a few bits in a byte, you first clear the bits with an AND operation and then you set the new values using an OR operation. Say I have loaded the following attribute byte from an attribute table: %10110011; This byte contains 4 palette indices, controlling the colors of a 32x32-pixel area. If I want to change only the upper left 16x16-pixel corner, I have to clear the bits for that area by ANDing the byte with %11111100, which will result in %10110000. Now I can simply ORA the new palette index, say, %00000010, and get %10110010, which I can write back to the attribute tables.

The problem with attribute tables is that reading from VRAM, modifying the data and writing it back is very inefficient. If you have to do a lot of attribute manipulation on on-screen areas, you might want to consider keeping a copy of the attribute tables in RAM, to avoid the trouble of doing it all during vblank.

infidelity
Posts: 340
Joined: Fri Mar 01, 2013 4:46 am

Re: refresher with setting bit(s) within palette attribute

Post by infidelity » Mon Aug 22, 2016 2:54 am

Wow thank for you being so in depth. Your example is perfect for my situation. Free space in ram is no issue for me with this small project I'm doing, so I can do as you suggested and have the ones I need modified stored in ram, modified when needed, then written to the attribute table.

I'll get to it tonight, many thanks yet again! I look forward to sharing what i've done when it's completed. :-)

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

Re: refresher with setting bit(s) within palette attribute

Post by tokumaru » Mon Aug 22, 2016 9:31 am

Glad I could help. There are a couple of things I didn't address in my previous post, but I assume you have an idea of how to handle them. For example, how you need to pick 1 out of 4 clear masks (℅11111100, ℅11110011, ℅11001111 or ℅00111111) depending on the corner you need to change. And you also need the new bits to be in the correct position for ORing, so you might need to shift the new palette index into position, or use a lookup table. Personally, I prefer to store the palette index repeated 4 times across a byte in each metatile definition, so I can just clear the unwanted copies before ORing.

infidelity
Posts: 340
Joined: Fri Mar 01, 2013 4:46 am

Re: refresher with setting bit(s) within palette attribute

Post by infidelity » Tue Aug 23, 2016 5:26 am

Using the OR function did the trick. :-) Before ppu rendering comes on, I load up the last 40 bytes of my attribute values to ram.then i turn ppu rendering on. I have a dedicated table which includes specific bits to be set to whichever attribute needs to be altered. So I have the byte loaded, the I OR it to the ram table, then I write that value to the actual attribute. It's 100% how I wanted it to work. :-) Thanks again!

Roth
Posts: 399
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Re: refresher with setting bit(s) within palette attribute

Post by Roth » Sat Sep 03, 2016 6:13 am

tokumaru wrote:Personally, I prefer to store the palette index repeated 4 times across a byte in each metatile definition, so I can just clear the unwanted copies before ORing.
That's pretty nifty! Does this mean you define your palettes in the 16x16 metatiles as opposed to 32x32 metatiles?

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

Re: refresher with setting bit(s) within palette attribute

Post by tokumaru » Sat Sep 03, 2016 8:51 am

Roth wrote:That's pretty nifty! Does this mean you define your palettes in the 16x16 metatiles as opposed to 32x32 metatiles?
Yup. Every now and then I feel tempted to do it in the 32x32s because in theory I could just transfer raw attribute bytes to the attribute tables, but then I remember the drawbacks:

1- Since I usually do horizontal + vertical scrolling, 32x32 blocks are only aligned to the attribute tables every other vertical screen, since each name table is 30 tiles tall, or 7.5 32x32 blocks, so I'd still have to manipulate individual bits. I could solve this easily by ignoring the bottom half of the last row of blocks instead of letting them spill into the next NT/AT, but that would make designing levels a little awkward, as I'd have to worry about blocks looking different depending on where they're used. Also, I'd have to account for the skipped parts when doing background collisions and such, which sounds like an unnecessary complications.

2- My designs often allow the destruction/collection of 16x16 blocks by replacing them with actual content rather than just blank tiles every time, meaning I might have to replace the palette index of a 16x16 area anyway. Sonic games on the Master System, which use 32x32 blocks all the way, solve this by having blocks with all combinations of 2x2 rings, for example (destruction only happen at the 32x32 level, though), but that's wasteful and not versatile at all.

Post Reply