tokumaru, thank you for helping us so much! ...Thank you to God too!! it's great to be here right now... I've got a lot of work to do and I'm so happpy!tokumaru wrote:You could arrange the metatiles in ROM kinda like this:
Here I have 3 metatiles, each using 6 bytes. If I want to get the collision info for any given tile, I can just put its index in X or Y and read it from the MetatileCollision table.Code: Select all
MetatileTile0: .db $00, $04, $08 MetatileTile1: .db $01, $05, $09 MetatileTile2: .db $02, $06, $0a MetatileTile3: .db $03, $07, $0b MetatileCollision: .db %00001010, %01001100, $00011010 MetatilePalette: .db %10101010, %00000000, %01010101
So, if your screenArray is an array of 16x15 metatile indexes, you can do something like this to read the collision info of any metatile:
Just as easily you now can use lda MetatileTile0, x to read the index of its top left tile, and the other tables to find out anything you want about the metatile in that position.Code: Select all
;use 2 4-bit coordinates to calculate ;how far in the array the metatile is lda metatileY asl asl asl asl ora metatileX tax ;get the index of the metatile lda screenArray, x tax ;get its collision information lda MetatileCollision, x
8x16 and whatever else unreg wants to know
Moderator: Moderators
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Have a small question... is a nametable set up kindof like this:
If so then I could incbin the nametable like I aleady do.
?tokumaru wrote:Code: Select all
MetatileTile0: .db $00, $04, $08 MetatileTile1: .db $01, $05, $09 MetatileTile2: .db $02, $06, $0a MetatileTile3: .db $03, $07, $0b
If so then I could incbin the nametable like I aleady do.
You can incbin the metatiles, but there are consequences...
I defined them interleaved like that (i.e. all the top left tiles first, then all the right left tiles, etc.) because it's easier/faster to access them that way. If they are not interleaved, you can't use the metatile index directly for reading tiles, instead you have to multiply it by 4 (since there are 4 tiles in each metatile). Also, because of that multiplication, you can't have more than 64 metatiles (256 indexes / 4 tiles = 64 metatiles) unless you use Indirect Indexed addressing (LDA ($XX), Y).
If you can still keep them interleaved in the file you are incbin'ing, great, but you'll have to do something like this to set up the labels to access each of the 4 tiles:
And then you can use the 4 labels normally.
I defined them interleaved like that (i.e. all the top left tiles first, then all the right left tiles, etc.) because it's easier/faster to access them that way. If they are not interleaved, you can't use the metatile index directly for reading tiles, instead you have to multiply it by 4 (since there are 4 tiles in each metatile). Also, because of that multiplication, you can't have more than 64 metatiles (256 indexes / 4 tiles = 64 metatiles) unless you use Indirect Indexed addressing (LDA ($XX), Y).
If you can still keep them interleaved in the file you are incbin'ing, great, but you'll have to do something like this to set up the labels to access each of the 4 tiles:
Code: Select all
MetatilesStart:
.incbin "metatiles.bin"
MetatilesEnd:
MetatileCount = (MetatilesEnd - MetatilesStart) / 4
MetatileTile0 = MetatilesStart
MetatileTile1 = MetatileTile0 + MetatileCount
MetatileTile2 = MetatileTile1 + MetatileCount
MetatileTile3 = MetatileTile2 + MetatileCount
Or unless you do like Super Mario Bros. and have four separate tables of metatiles, selected by bits 7 and 6 of the metatile number. These upper 2 bits are also used as the attribute value.tokumaru wrote:Also, because of that multiplication, you can't have more than 64 metatiles (256 indexes / 4 tiles = 64 metatiles) unless you use Indirect Indexed addressing (LDA ($XX), Y).
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
tokumaru, thank you so much for that consequences explanation! I thought about this idea a lot during the past 2 days.
After me thinking and praying about what to do, my sister and I chatted about what yall have told us for around 2 hours! It was a great time; we finally decided to not try to .incbin the nametables because of all of the consequences. We also decided to try to not make mistakes during the conversion process; it was that or to accept using a faster-and-slower-more-confused-programming way of thinking about this collision process ("faster" bcause there would be no conversion-of-every-nametable time spent). But, she wawnts to convert our nametables to the new format that tokumaru mentioned because she had run out of game-work to do due to my lengthly programming stumbling along... way.
tepples, it was fun to think about doing this Nintendo's way.
You are amazing and that's awesome to know, thank you tepples!tepples wrote:Or unless you do like Super Mario Bros. and have four separate tables of metatiles, selected by bits 7 and 6 of the metatile number. These upper 2 bits are also used as the attribute value.tokumaru wrote:Also, because of that multiplication, you can't have more than 64 metatiles (256 indexes / 4 tiles = 64 metatiles) unless you use Indirect Indexed addressing (LDA ($XX), Y).
After me thinking and praying about what to do, my sister and I chatted about what yall have told us for around 2 hours! It was a great time; we finally decided to not try to .incbin the nametables because of all of the consequences. We also decided to try to not make mistakes during the conversion process; it was that or to accept using a faster-and-slower-more-confused-programming way of thinking about this collision process ("faster" bcause there would be no conversion-of-every-nametable time spent). But, she wawnts to convert our nametables to the new format that tokumaru mentioned because she had run out of game-work to do due to my lengthly programming stumbling along... way.
tepples, it was fun to think about doing this Nintendo's way.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Why would you say each metatile uses 6 bytes? Each byte in the first metatile is for a 16x16 area, except the MetatilePalette byte that covers a 32x32 area. Wouldn't each metatile use 5.25 bytes? edit: , I dont know if 5.25 bytes would be the correct number... that is what my sister and I came up with; I am trying to figure out how to fill the MetatilePalette parts of our NametableCollision files.tokumaru wrote:You could arrange the metatiles in ROM kinda like this:
Here I have 3 metatiles, each using 6 bytes.Code: Select all
MetatileTile0: .db $00, $04, $08 MetatileTile1: .db $01, $05, $09 MetatileTile2: .db $02, $06, $0a MetatileTile3: .db $03, $07, $0b MetatileCollision: .db %00001010, %01001100, $00011010 MetatilePalette: .db %10101010, %00000000, %01010101
32x32 Metatile definition as described by tokumaru.
Requires:
A byte for the top left tile. 1 byte total
A byte for the top right tile. 2 bytes total
A byte for the bottom left tile. 3 bytes total.
A byte for the bottom right tile. 4 bytes total.
A byte for the collision information. 5 bytes total.
A byte for the palette information. 6 bytes total.
Requires:
A byte for the top left tile. 1 byte total
A byte for the top right tile. 2 bytes total
A byte for the bottom left tile. 3 bytes total.
A byte for the bottom right tile. 4 bytes total.
A byte for the collision information. 5 bytes total.
A byte for the palette information. 6 bytes total.
Heh, I guess the way I defined the palettes can cause some confusion... If you pay attention you'll see that I just repeated the same 2 bits 4 times in each byte. That's because depending on where the metatile is used, its 2 attribute bits will in one of 4 different places of a byte, so if have the same bits in all 4 positions you can just mask out the ones you don't need.
That's a waste of space, yes, since each byte has the same information 4 times. That was just an example though, and you can certainly use other methods. Maybe doing it like SMB, as tepples suggested, would be a good idea.
That's a waste of space, yes, since each byte has the same information 4 times. That was just an example though, and you can certainly use other methods. Maybe doing it like SMB, as tepples suggested, would be a good idea.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
tokumaru wrote:Heh, I guess the way I defined the palettes can cause some confusion... If you pay attention you'll see that I just repeated the same 2 bits 4 times in each byte. That's because depending on where the metatile is used, its 2 attribute bits will in one of 4 different places of a byte, so if have the same bits in all 4 positions you can just mask out the ones you don't need.
That's a waste of space, yes, since each byte has the same information 4 times. That was just an example though, and you can certainly use other methods. Maybe doing it like SMB, as tepples suggested, would be a good idea.
Thank you for reading all of my post... yes, I guess my point could have been explained better. I'm sorry. Glad you understood me though!
Ok, I understand much better after talking it over with my sister. Right now, I don't understand what you mean by, "maybe doing it like SMB, as tepples suggested, would be a good idea." But, I'm going to chat with my sister about that tonight; maybe I'll learn a bit of what you ment. I think I'll be able to post tomorrow night what I learned. good night yall. : )
I just meant that you could use the top (or bottom, it's up to you) 2 bits of the metatile index to specify the palette it uses, that way each metatile would be defined in only 5 bytes.
If you don't want to be restricted to only 64 metatiles, you can do *exactly* like SMB and have the palette bits double as metatile bank selectors. That way you can still have 256 metatiles, but divided in 4 groups of 64, and all the metatiles of the same group use the same palette.
It's a fairly compact format, and should work well for most games.
If you don't want to be restricted to only 64 metatiles, you can do *exactly* like SMB and have the palette bits double as metatile bank selectors. That way you can still have 256 metatiles, but divided in 4 groups of 64, and all the metatiles of the same group use the same palette.
It's a fairly compact format, and should work well for most games.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
tokumaru, when you say "metatile index" what does that mean? Is it a number that I'm susposed to give each metatile? This is not worked out well enough in my head... yet. Yes, I would like to set the upper two bits of this metatile index to the pallet and decrease the number of bytes used for each metatile!
I thought that we wouldn't be limited to 64 metatiles because our tile data will be interleaved (like you talked about). : )
I thought that we wouldn't be limited to 64 metatiles because our tile data will be interleaved (like you talked about). : )
An "index" is a number you use to access something. Since metatiles are dfined in the ROM sequentially, you can use numbers to access them. The first one is index 0, the second one is index 2, and so on. So if you are gonna use the metatile indexes to specify palettes, you just have to pay attention to the order in which you define them. Metatiles that use palette 0 must be between 0 and 63, metatiles that use palette 1 must be between 64 ans 127, and so on.
If you really plan on having only 64 metatiles at a time, you can have your screen array use only one byte for both the metatile index (6 bits) and the palette index (2 bits). That way you just have to mask out the bits you don't need depending on the info you want to use. For example, after calculating the position of the metatile in the screen array:
You can do this to load its index (which you can then use to read tiles or collision information):
Or you can AND the value with %11000000 instead to keep only the palette bits, which you'll need in order to compute the attribute table data.
If you really plan on having only 64 metatiles at a time, you can have your screen array use only one byte for both the metatile index (6 bits) and the palette index (2 bits). That way you just have to mask out the bits you don't need depending on the info you want to use. For example, after calculating the position of the metatile in the screen array:
Code: Select all
;calculate the position of the
;metatile from its coordinates
lda metatileY
asl
asl
asl
asl
ora metatileX
tax
Code: Select all
;get the index of the metatile
lda screenArray, x
and #%00111111 ;remove the palette bits
tax
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
tokumaru, thank you for all of your help!
I'm having a new problem... the attribute bits are bothering me because I must have more than 64 metatiles. So I thought maybe since the two attribute bits are important I could store 4 pairs of attrilbute bits in a byte... in my head i would need 15 rows of 4 bytes to hold all of it. So that is close to the 8 byte by 8 byte attribute table representation in the nesdev wiki. Why does the nametable attribute table need 64 bytes? I think it should have 60 bytes. But it needs 64...
I'm having a new problem... the attribute bits are bothering me because I must have more than 64 metatiles. So I thought maybe since the two attribute bits are important I could store 4 pairs of attrilbute bits in a byte... in my head i would need 15 rows of 4 bytes to hold all of it. So that is close to the 8 byte by 8 byte attribute table representation in the nesdev wiki. Why does the nametable attribute table need 64 bytes? I think it should have 60 bytes. But it needs 64...
Yes, there are unused bits in the attribute tables. The reason why the PPU uses 64 bytes rather than 60 is because the attributes are arranged in squares. The bottom half of the last row of squares doesn't have correspondent tiles in the name table, because the name table is only 30 tiles high, so there are indeed a total of 32 bits (4 bytes) that don't do anything, but they are still part of the attribute tables because they share bytes with bits that ARE used.unregistered wrote:Why does the nametable attribute table need 64 bytes? I think it should have 60 bytes. But it needs 64...
I'm not gonna lie to you, attributes can be pretty hard to manage. Having to shift and combine bits to for the attribute bytes is not something you can easily do without some good amount of planning. So take your time, draw it all on paper and think hard about it, eventually you'll find a solution that works for you.
As I said before, quite a few NES games used 32x32-pixel metatiles, because that's the exact size of the area affected by an attribute byte. This means that the program can easily write the attribute bytes straight to the attribute table, without any sort of processing. I'm not saying this is the best solution for all cases, but if you're really having a hard time with attributes, this is the easiest solution there is.