It makes sense, to me at least, to update the tables in chunks when scrolling horizontally with vertical mirroring. For example, you move right four tiles and then you update a vertical chunk of attribute tables. You could even buffer the attribute data of columns as you draw them and then once you've drawn 4 columns, update the attribute tables if you needed.
However, once you bring the four way scrolling into play I start to get a little confused. Would the best way to do it be updating the attribute tables for four tile chunks when you scroll left and right, but keep a buffer or something for updating them with a vertical scroll?
Does that make sense, or am I way off course here?
However, for updating attribute tables, I suggests a method who works with 2x2 blocks, which computes the VRAM adress using lockup tables (to make things relatively simple), and does AND/OR operations with the older value. You can do that either by read-modify-write $2007 (needs to be in VBlank), or by using one/two $40 bytes tables in memory that "mirrors" the attribute table for logic, and update it to RAM on next VBLank.
Personally, I have done what Bregalad suggested. I have a copy of the attribute tables in RAM, and I modify each 16x16-pixel square individually, using masks. Then during VBlank, I just copy entire rows or columns of attribute bytes.
Accessing the bits can be really easy: based on the address of the tile you can easily locate the corresponding attribute byte and bits. Since the name table is 32x30 tiles, the address of a tile is defined like this: YYYYYXXXXX. Just combine the 3 highest bits of each coordinate to find the address of the attribute byte, like this: YYYXXX. Then, combine bit 1 of each coordinate (bit 0 is not needed for anything, because the NES doesn't assign attributes to individual tiles) to form an index into tables of masks that will be used for bit manipulation:
Code: Select all
AttributeMasks: .db %00000011 .db %00001100 .db %00110000 .db %11000000