Purpose of metatile height + width

Post Reply
amellors
Posts: 4
Joined: Sat Oct 20, 2007 6:02 pm

Purpose of metatile height + width

Post by amellors » Sat Oct 20, 2007 10:53 pm

What is the purpose of this option?

Especially as it relates to Maps and Sprites.

Thanks

WinterMute
Site Admin
Posts: 1478
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Purpose of metatile height + width

Post by WinterMute » Sat Nov 03, 2007 4:58 am

Sorry to take a while getting to this, it's a fairly convoluted subject and needed some thought to compose a good response.

The DS hardware operates in units of 8x8 tiles and everything in the tile ( or character ) based modes is composed of these base units. In the case of backgrounds you can only display 8x8 tiles but there are some tricks you can use to have maps in larger units - more on that later.

Although sprites can be several sizes they are still made up from clusters of these 8x8 tiles - for instance a 32x32 sprite consists of 4x4 = 16 of the basic tiles in VRAM. Clustering tile units in this way is known as metatiling and the 32x32 sprite would be a 4x4 metatile. In the normal 1 dimensional VRAM mapping these tiles are arranged by column then row, i.e. the first 4 tiles define the 32x8 pixel area at the top of the sprite. We can also arrange things in a 2D map but that's something probably best left for a later tutorial, it's not something that gets used often.

The primary purpose of metatile width and height is to allow us to specify the tile clustering for a given sprite size and so avoid having to preprocess the input graphic to get the correct tile order. -Mw specifies the number of tiles wide & -Mh specifies the number of tiles high. In our 32x32 sprite we would use -Mw4 -Mh4.

With backgrounds we're kind of stuck with the 8x8 tiles for rendering but we can still metatile in software. This can be useful for large maps because it reduces the storage requirements for the map array - if we use 16x16 tiles for the background then we only need a single entry for every 4 tiles that are actually displayed and a single 8x8 tile can be reused in multiple 16x16 tiles. Grit will output two maps in this case, one is a set of arrays which define the tiles used to create the metatiles and the other is like a standard map but indexes into the metatile array.

Here's a little code snippet to draw a metatiled map into a background. I was using this to fake 12x12 tiles by using 3x3 (24x24) metatiles on an extended rot/scale backdrop and scaling down to half size. In case you're wondering, I couldn't use 16x16 because the scaling is nearest neighbour and caused weird artifacts.

This was a fairly quick hack I haven't really tidied up so excuse the magic numbers. The maps in the game were 26x16 12x12 tiles. The 128 is the offset to the next line on a 1024x1024 background.

Grit also confused me a little here since the <file>MetaMap variable it outputs in the header is the map of metatiles and the <file>Map is the array of metatile mappings ( i.e. the 8x8 tile indices which form the metatile). I've been used to thinking of those the other way round but that may well be just a fault in my own terminology.

Code: Select all

//---------------------------------------------------------------------------------
void drawJetMap(jetLevel *map, u16 *destMap) {
//---------------------------------------------------------------------------------

	int x,y = 0, index;
	short tile;
	u16 *dest = destMap;
	

	for ( y = 0; y < 16; y++ ) {
		for ( x = 0; x < 26; x++ ) {

			tile = map->tilemap[ y * 26 + x];

			tile = jet_tilesMetaMap[tile];
			u16 * meta = (u16*)&jet_tilesMap[tile*9];
			
			for ( index = 0; index < 3; index++ ) {
				dest[index]			= meta[index];
				dest[index + 128]	= meta[index + 3];
				dest[index + 256]	= meta[index + 6];
			}
			dest += 3;
		}
		dest += (128 * 3) - (26 * 3);
	}
}
Help keep devkitPro toolchains free, Donate today

Personal Blog

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests