8x16 and whatever else unreg wants to know

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

unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru wrote:You could arrange the metatiles in ROM kinda like this:

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
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.

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:

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
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.
tokumaru, thank you for helping us so much! :D ...Thank you to God too!! :D it's great to be here right now... I've got a lot of work to do and I'm so happpy! :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Have a small question... is a nametable set up kindof like this:
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. :? :D
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

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:

Code: Select all

MetatilesStart:
	.incbin "metatiles.bin"
MetatilesEnd:

MetatileCount = (MetatilesEnd - MetatilesStart) / 4

MetatileTile0 = MetatilesStart
MetatileTile1 = MetatileTile0 + MetatileCount
MetatileTile2 = MetatileTile1 + MetatileCount
MetatileTile3 = MetatileTile2 + MetatileCount
And then you can use the 4 labels normally.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

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).
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.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru, thank you so much for that consequences explanation! :D I thought about this idea a lot during the past 2 days.
tepples wrote:
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).
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.
You are amazing and that's awesome to know, thank you tepples! :D

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. :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru wrote:You could arrange the metatiles in ROM kinda like this:

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
Here I have 3 metatiles, each using 6 bytes.
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: :oops:, 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.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

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

Post by tokumaru »

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.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

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. :oops: 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. : )
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

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.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru, when you say "metatile index" what does that mean? :oops: 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! :D

I thought that we wouldn't be limited to 64 metatiles because our tile data will be interleaved (like you talked about). :) : )
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

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:

Code: Select all

	;calculate the position of the
	;metatile from its coordinates
	lda metatileY
	asl
	asl
	asl
	asl
	ora metatileX
	tax
You can do this to load its index (which you can then use to read tiles or collision information):

Code: Select all

	;get the index of the metatile
	lda screenArray, x
	and #%00111111 ;remove the palette bits
	tax
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.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru, thank you for all of your help! :D
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... :?
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

You can split that data away from that data and then use all 8-bits per metatile and then read the data from an attribute table for them too, and like you said use 1 byte for 4 attributes. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

unregistered wrote: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.

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.
Post Reply