Okay, so I'm working on doing some 4 way scrolling, but updating the attribute tables is getting to me.
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?
Attribute Tables and 4 way scrolling.
Moderator: Moderators
4 way scrolling is a total pain to get working, I never got any fully working personally despite multiple tries.
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.
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.
Useless, lumbering half-wits don't scare us.
This is kinda annoying to get right on the first time. The main problem is that the name tables are 30 tiles high instead of 32, so the attribute bytes don't align properly across adjacent vertical screens.
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:
I usually copy to RAM the masks I'm gonna need to RAM (when rendering column of metatiles for example, I need one mask for the top block and another one for the bottom block, and I alternate between them) so that the index registers can be use to access the array of new attributes and the mirror of the attribute table.
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