16x16, 32x16, or 32x32: What are the advantages and disadvantages of different metatile sizes, and which commercial games use which sizes?
SMB1, SMB2, SMB3: 16x16
Sorry to sound dumb but, what is a metatile?
I have been giving a lot of thought on metatiles/block sizes lately, as I was trying to figure out the best possible format for the levels in my game. I have the following considerations on the matter:
The advantege of 16x16 blocks is that you'll get an overall better resolution in your level and use less space to store the set of blocks. However, 240 bytes to define each screen in the level is a bit too much. You could use compression, but then you'd get one of the following problems: If you decompress the whole level at the start of it (you'd need the extra 8k of RAM, of course) your levels would have to be fairly small. I think this is done on MC Kids, and it does have small levels. Or if you tried to do some sort of real-time decompression it could be quite time-consuming.
Then you think about using 32x32 blocks, wich, in the NES, has the advantage of matching the area covered by an attribute byte, freeing you from complex, time-consuming bit manipulation (if you're scrolling sideways only, as the height of the NES screen is not a multiple of the number of attribute bytes in a column). However, defining 256 of these will take at least 4608 bytes (16 byte for the tile map, 1 for the attributes and 1 for the type of the block - but you also could have the types match ther indexes and don't use a type byte at all -). This way you could have levels 4 times as large as those using 16x16 blocks using the same memory.
The game I'm working on is a Sonic the Hedgehog kind of thing, so I researched games of the kind:
Somari, the pirate Sonic clone for the NES, uses 16x16 blocks. It has a handfull of screen maps using these blocks (in fact, if you use an hex editor like the one in FCEUXD, aligned with 16 columns, in the *ROM*, you'll easily spot the screen maps, and if you alter them you can see the results immediately, it's fun), and the actual map indexes those screens. If you play through the game you'll see a lot of repeated background. I like this idea though... the repeated screens are not all that obvious to notice when playing.
Sonic 2 for the Master System (I know it is not NES, but...) uses 32x32 blocks, and the level maps are RLE compressed in the ROM and decompressed to RAM for playing.
The Megadrive (not NES again, ok, but still usefull info!) Sonic's use an interesting format: it uses 16x16 blocks (I don't know how many, but more than 256) that are used to form the 256 128x128 blocks that are actually used in the level. This makes it possible to have huge levels! And I don't know about you guys, but I never thought Sonic was repetitive, in spite of using such large blocks.
With all of that in mind, I settled for my level format. I use 256 16x16 blocks, used to form 240 64x64 blocks, used to form 240 256x256 blocks/screens that are mapped through the level map. It may seem complicated, but my implementation of the decoding routine seems to run fast enough for a fast game, and allows me to have levels as large and complex as those on the Megadrive Sonic's (up to 8192x8192 pixels or anything using the same area but with different proportions).
Each of my levels use a 16K bank of ROM, including everything needed for the level map, height/collision maps for a few of the blocks, all object definitions/placement for that level (objects themselves are elsewhere), and routines for events triggered by screens in the level. If there are "acts", like in Sonic (that share the same graphics/blocks/objects), they can use the same 16K if they all fit there.
tokumaru wrote:
The Megadrive (not NES again, ok, but still usefull info!) Sonic's use an interesting format: it uses 16x16 blocks (I don't know how many, but more than 256) that are used to form the 256 128x128 blocks that are actually used in the level. This makes it possible to have huge levels! And I don't know about you guys, but I never thought Sonic was repetitive, in spite of using such large blocks.
Metroid works very similarly to this, having numerous levels of map data:
1. A global world map, 32 screens wide and 32 screens tall. Each byte loads data from a room table.
2. Up to 255 room maps, each 16x15 blocks in size. Each 3-byte sequence loads data from an object table.
3. Up to 255 objects, consisting of rectangular groups of blocks. Each object starts with a 'width' byte, followed by rows of blocks loaded from a Block table and stopping once it hits a row starting with 0xFF.
4. Up to 255 blocks, each 16x16 pixels in size. Each block consists of 4 graphical tiles.
On top of that, it switches banks at various points in the game (Brinstar, Norfair, Ridley's Lair, Kraid's Lair, Tourian) and loads new room/object/block tables each time.
A more detailed explanation can be found
here.
Quietust wrote:
Metroid works very similarly to this, having numerous levels of map data:
You really found them similar? I just read the page you pointed us to, Metroid's levels look much more like SMB1's (when it comes to storage format) levels to me. You know, the level beeing made up of objects (structures, in that document) placed around the screen only where needed. You may have said that based on the indirect way of forming the level, though (this indexes that, that indexes that other thing, that indexes tiles).
The Sonic-type of level has a block index in all positions, if you want nothing in a place you have to use an empty/transparent block, but still a block.
I guess the difference between these two kinds of level formats is roughly the difference between vector graphics and bitmap graphics. Bitmap graphics describe what color goes exactly in every pixel, while vector graphics describe shapes arranged to look like the picture we want to represent.
The way Metroid organizes it's level can be very compact, that's a very good thing. The bad part is that it has to render a full screen at a time. And this is only possible if you use horizontal OR vertical scrolling/mirroring, not both. Unless you have 4-screen mirroring, but then you'd have to render 2 screens at a time, wich could be very slow depending on the complexity of the screens. So I say it is not very feasible for a more complex game.
By the way, I never played Metroid very much and can't seen to remember, and based on screen shots I've seen I ask: does it use only 1 palette for the background? That game looks so ugly that I wouldn't be surprised if it didn't do any kind of maintenance on the attribute table besides clearing it all to the same value.
The main difference is that the Sonic games effectively use fixed-size objects all aligned on object boundaries, compared to Metroid which allows variable size objects aligned on a block boundary.
The Mario games use a method similar to Metroid, except with much larger rooms (and allowing simple items like bricks and coins to be tiled to arbitrary sizes).
Also, it isn't necessary to render a full screen at a time - it just needs to be decoded into RAM (usually WRAM at $6000-$7FFF) and then written to the screen as it scrolls - 8KB of RAM is plenty to hold at least several screens worth of level data.
Metroid most certainly does use multiple background palettes - it's just that most of the beginning rooms are done with only one palette.
Quietust wrote:
Sonic games effectively use fixed-size objects all aligned on object boundaries, compared to Metroid which allows variable size objects aligned on a block boundary.
You could describe the Sonic levels like this, but it is just harder. =) I still thing the fact that you must or mustn't place something in all avaliable spaces play an important difference between the techniques.
Quote:
The Mario games use a method similar to Metroid, except with much larger rooms (and allowing simple items like bricks and coins to be tiled to arbitrary sizes).
Also, the way the levels are stored there imposes the limit of the player not beeing able to go back. I guess it's because most of the encoding is RLE-based, wich means you don't know where the objects end, making it really hard to render backwards (without extra memory).
Quote:
Also, it isn't necessary to render a full screen at a time - it just needs to be decoded into RAM (usually WRAM at $6000-$7FFF) and then written to the screen as it scrolls - 8KB of RAM is plenty to hold at least several screens worth of level data.
Yeah, I've been a bit fuzzy with the verbs lately, I've been writing down many ideas on level storage/decoding/rendering these days... when I said "rendering" I meant "decoding", not necessarilly writing to the nametables and all. I don't know, if you can sport 8KB of WRAM you could use a less compact format for the levels and use a few more KB of ROM. I'm planning my game to use only the stock 2KB of RAM, and it will have big levels, enemies/objects that don't come back to life (if they shouldn't) and will remember the positions of objects/enemies while the player is still somewhat close to them, but my levels will most likely use 16KB each. I guess this is a matter of preference... today, that is... back then it was mostly about money, I'm sure! =D
Quote:
Metroid most certainly does use multiple background palettes - it's just that most of the beginning rooms are done with only one palette.
OK, it's just that I couldn't picture/recall any.
tokumaru wrote:
Also, the way the levels are stored [in SMB1] imposes the limit of the player not beeing able to go back. I guess it's because most of the encoding is RLE-based, wich means you don't know where the objects end, making it really hard to render backwards (without extra memory).
But SMB1 does use a sentinel value between screens (drawn as "next page" in YY-Mario Editor), and a bidirectional engine could seek back to the start of the previous screen and decode from there. From what I've seen of Lunar Magic, I believe SMW (snes, not the nes pirate version) works this way.
tepples wrote:
16x16, 32x16, or 32x32: What are the advantages and disadvantages of different metatile sizes, and which commercial games use which sizes?
Castlevania series uses 32x32. The engines i've written for commercial GBC and GBA titles have all used 16x16 metatiles.
As your metatiles get larger, your artists get sadder, as it becomes more tedious to put together convincing artwork. Also, your returns begin diminishing, as you've likely cut your map data size by roughly 4, and your actual tile data sizes start to become the limiting factor.
Interestingly enough, our nextgen texture artists are going back to tiling: they're using a technique where they create a texture 'tileset' much like on handheld, then create tiled texture arrangements which are created at runtime via render-to-texture. Back to basics.
tepples wrote:
But SMB1 does use a sentinel value between screens (drawn as "next page" in YY-Mario Editor), and a bidirectional engine could seek back to the start of the previous screen and decode from there.
Well, it has been prepared to move forward only, but could move back with little extra effort. Since the screens in SMB1 have variable byte size, you'd need pointers to access them randomly. In the case of Mario, it would be possible to scroll back by placing a pointer to the previous screen, or even the length in bytes of the previous screen, so we know how much to go back and start decoding.
At first I thought about using compressed screens with pointers to them. But as this was for an multi-way scroller, each screen needed to point to 4 others (Mario can get away with pointing only to the previous one, as the next is just at the end of the current one), what resulted in 8 bytes just to connect the level together. Even if each screen had 8 bit codes (wich would result in 4 bytes for connections) and a 512 byte table of pointers to each screen it was still a lot of wasted space. I then decided to abandon this idea and have a standard rectangular level map, with each position holding the index of a screen map.
So, using pointers to other screens may be bad sometimes. The advantage is that you'll not waste space defining areas the player will never go to. I don't think it pays off though. Any gains from not defining unvisitable screens will be lost because of the absurd ammount of data needed to interconnect the screens.
Maybe SMB1 could just store a long string of pointers to the screen, so that they could be accessed at will. But then it would have to be prepared for a lot of other things, like not restoring coins and enemies, for example. And I believe the Mario ROM is already so full there wouldn't be any room for this kind of new features, maybe that's why they left it that way.
The game I'm doing now uses 32x32 blocks, which are themselves constitued of four 16x16 metatiles, giving maps very light in bytes (additionnal to a small RLE like compression applied to blocks) and having a decent level design allowed. I can store 64 different metatiles and 32 different blocks at the same level.
Quote:
Then you think about using 32x32 blocks, wich, in the NES, has the advantage of matching the area covered by an attribute byte, freeing you from complex, time-consuming bit manipulation (if you're scrolling sideways only, as the height of the NES screen is not a multiple of the number of attribute bytes in a column).
This is a real advantege horizontally, but you still have to split attributes nybbles when scrolling vertically.
Why coudn't the NES use a 256x192 pixel screen? This is proportional to the 4:3 TV screens we use with the NES, so there would be no problems regarding distortions or stuff like that. Also, this would leave 256 bytes for use with attributes, 4 times what we have now, enough for each tile to use it's own palette. Working with matatiles would be a piece of cake since each attribute byte would represent a 16x16 pixel block.
The design nintendo chose is strange... a screen with the strange proportions of 256x240, the last row of attributes having unused bits... it's just weird. It would all fit better if they used 256x192. I think that is the Master System's resolution.
Well, I cannot know why, but effectively, I think you're right. The SNES also have a 256x240 screen. I think it has better resolution like that, but yeah, that causes others problems as well.
I'm sure this resolution works fine with the SNES since it already uses 2 bytes to define each tile in the screen, meaning the palettes have tile precision among other nice things.
But the fact that if they had sacrificed a little resolution (256x192 does not look bad on screen at all!) on the NES we'd get better control of the attributes and better looking gfx bugs me a lot.
Unlike PC monitors, TV monitors are fixed at a 240 or 288 line The Apple II, the ZX Spectrum, and the Commodore 64 all used 192-line-tall video modes, and their TV pictures all had big ass borders.
I'm guessing that Nintendo used a nearly full-frame video mode (we decided in that other thread that a full ntsc frame would be 280x243 NES pixels, and my tests on an old Mac bear this out) because the NES PPU is just a home version of the PPUs in Nintendo's Radar Scope through Mario Bros. era arcade boards, which used 256x224 pixels to address the full open-frame screen. (Yes, Donkey Kong is officially listed as 224x256 vertical.)
And quite a few Sega Master System (NTSC) games used the TI video chip's 256x224 pixel video mode to hide the borders and take the hit in vblank time.
edit: minor correctness fixes
Another advantage to 2x2 meta tiles is that collision detection is SO much easier, since there aren't more than $FF meta tiles on screen at once. You can read the bytes of maps easier, you can just read map,x to read any tile on the screen, due to there only being $FF tiles. This is why making my
NES meta tile layer was so easy to do.
The NTSC C64 has 262 lines, with 200 of them being addressable screen.
Celius wrote:
Another advantage to 2x2 meta tiles is that collision detection is SO much easier, since there aren't more than $FF meta tiles on screen at once. You can read the bytes of maps easier, you can just read map,x to read any tile on the screen, due to there only being $FF tiles. This is why making my
NES meta tile layer was so easy to do.
What you say here is a nonsense. Having 2x2 or 4x4 collision detection changes strictly nothing to how easy or hard collision detection is. And how much metatiles on screen at once there is, your engine determine it totally independantly of the meatile size. I've done collision detection without trouble with my block system I descibed above.
LocalH wrote:
The NTSC C64 has 262 lines, with 200 of them being addressable screen.
These lines consist of roughly 20 lines of border, 200 lines of picture, 20 lines of border, and 22 lines of vblank. Some hardware producers don't like a lot of border.
Bregalad wrote:
What you say here is a nonsense. Having 2x2 or 4x4 collision detection changes strictly nothing to how easy or hard collision detection is. And how much metatiles on screen at once there is, your engine determine it totally independantly of the meatile size. I've done collision detection without trouble with my block system I descibed above.
I disagree. When doing collision detection with a 32x30 map, it really complicates things, because you have to deal with changing the high byte of the map address. You usually load bytes with indirect indexed addressing, and you have to do many routines with comparing Y positions, and changing high bytes. Okay, it's a little hard to explain, but my collision detection code for 32x30 was WAY longer and WAY more complicated than my 16x15 map. You don't have to use indirect indexed addressing for such a thing. Well, you probably should to be a little more relative with the routines, but you could just say map,x to load any byte of the map, where as you cannot with 32x30 maps, because there are more than $FF bytes.
Celius is right by saying it is easier to work with the maps if you can access the whole screen by modifying only the index register and not the base address.
But then again, any block size from 16x16 up will grant you that possibility, and not many games will work at the tile-level, as it wastes a lot of space. I think only really old, static screen kind of games used tile-level maps. Anything newer than that will most likely use 16x16 or more.
tepples wrote:
LocalH wrote:
The NTSC C64 has 262 lines, with 200 of them being addressable screen.
These lines consist of roughly 20 lines of border, 200 lines of picture, 20 lines of border, and 22 lines of vblank. Some hardware producers don't like a lot of border.
On the other hand, the C64 has a huge horizontal border - quite a few more pixels per line outside of blanking as compared to something like the Genesis. Also, the 262 line C64's are only the earlier ones with 64 cycles per line - the newer 65-cycle NTSC VIC-IIs have 263 lines. And, for completeness, the PAL C64 has 63 cycles per line and 312 lines.
Celius wrote:
I disagree. When doing collision detection with a 32x30 map, it really complicates things, because you have to deal with changing the high byte of the map address. You usually load bytes with indirect indexed addressing, and you have to do many routines with comparing Y positions, and changing high bytes. Okay, it's a little hard to explain, but my collision detection code for 32x30 was WAY longer and WAY more complicated than my 16x15 map. You don't have to use indirect indexed addressing for such a thing. Well, you probably should to be a little more relative with the routines, but you could just say map,x to load any byte of the map, where as you cannot with 32x30 maps, because there are more than $FF bytes.
So that means that having 8x8 metatiles is harder than having 16x16 metatiles, wich I agree with you. However, 16x16 metatiles aren't in any way easier or harder than 32x32 metatiles at this level, they're just different.
In an advanced RPG, you'll want to have large scrolling maps, so even with 16x16 metatiles, the larger maps will easily get larger than 256 bytes once decompressed. It sure is a bit more odd to handle, but no programmer should flee against difficulty anyway.