Another Final Fantasy question

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Another Final Fantasy question

Post by Celius »

I am currently working on a Final Fantasy project, and I was wondering about Final Fantasy's maps. Are they based on 2x2 meta tiles? Do they have different sizes? I'm really really concerned that I may not have enough space for maps, and I'm wondering how the other Final Fantasies work. Does anybody know how they conserve space? Like Final Fantasy 3 for instance? Any multiple size metatiles?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

A lot of games use "object oriented" maps, where each element of the map has a type, x, y, width and height, and those are rendered into a metatile map in RAM before being drawn to the nametables. Super Mario Bros. uses a primitive version of this technique; Super Mario Bros. 3 and Super Mario World implement it exactly as I just described it.

As for games whose map structure is still a grid, Pokémon is said to use 32x32-pixel metatiles. Sonic the Hedgehog 2 uses run-length encoding and 128x128-pixel (!) metatiles, which is acceptable because the player moves so fast that he or she doesn't see the repetition.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

All 8-bit Final Fantasy games (including Final Fantasy Legend and Adventure for game boy, even if they're not real FF games) works on 16x16 metatiles.
The games probably use some trick to reduce the size of the maps. There is many compression algorithms, begining with RLE, that can easily shut the size down to 20% of the original one, and because they run with additionnal RAM, it is easy to use a lot of RAM to have all used maps decompressed in RAM.
If you want to know more, try to reverse-engineere them to have a better idea of how they works.
Useless, lumbering half-wits don't scare us.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

tepples wrote:Sonic the Hedgehog 2 uses run-length encoding and 128x128-pixel (!) metatiles
These are indeed very large metatiles! But even with such large construction blocks they can pull levels that look much more interesting than the ones in the GBA Sonic games.

I think they use some sort of LZ compression, not RLE. The whole level is decompressed to RAM at once, on level start. The 128x128 metatiles are made of 16x16-pixel metatiles though, not individual tiles. The SMS version of Sonic 2 uses RLE compression and 32x32-pixel metatiles, that are placed directly in the levels. The levels are also fully decompressed to RAM when the level starts.

Celius, I can't tell you how they do it in Final Fantasy. But if you want to have large maps you will most likely need to chose one of the following:

1. object-based levels, where every screen starts empty and is filled with objects at specifyed positions, in RAM;
2. grid-based with compression, where you decompress the screens to RAM as the player moves;
3. grid-based with heavier indirection, as in the Sonic series, where you have more than 1 level of metatiles.

For my current game I chose option 3, since that seems to be the only option that does not require extensive use of RAM. I use 16x16-pixel metatiles that are used to make 64x64-pixel metatiles that are used to make 256x256-pixel screens that are used to form the level. May seem complicated but allows for very large maps, needs no compression/decompression algorithms and needs no extra RAM, you can access everything directly from ROM.
Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

Thank you all for that information. I have one question though.
tepples wrote:those are rendered into a metatile map in RAM before being drawn to the nametables
Why is that? Why are they rendered into RAM before being drawn to name tables? I've always wondered why people say a map has to be decompressed before it can be compressed in RAM or something like that, I thought it was all nonsense. Why the heck does it have to be decompressed before compression? I think I may be translating this into my brain incorrectly. I really don't know what everyone's talking about. Will someone please clarify this?[/quote]
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Celius wrote:
tepples wrote:those are rendered into a metatile map in RAM before being drawn to the nametables
Why is that? Why are they rendered into RAM before being drawn to name tables?
Most general-purpose data compression schemes require data to be read out in strict sequence, such as from left to right and top to bottom. Arbitrary scrolling maps are specifically not read out in strict sequence; the RAM is used as a buffer to allow random access to inherently sequential data.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Celius wrote:Why is that? Why are they rendered into RAM before being drawn to name tables?
Because you draw ROWS and COLUMS of tiles to the name tables. If your map is not arranged in the form of rows and columns, as happens with grid maps but not with object based maps, you'll have a hard time translating that to rows and columns in real time.

I don't know if you know that Celius, but when the screen scrolls, you only draw what is new, in the form or rows and columns. When your screens are compressed or arranged with objects, thare is no way you can read rows or columns from there unless you decompress/render them to RAM first, where the map will be arranged in the form of grids.

You could render a non-grid map to the name tables IF you didn't use scrolling, since in that case you could just shut rendering off and take your time to draw all you want to the screen - object by object, or by full decompression of the compressed screen. But with scrolling, you only have time to draw a few rows and/or columns of tiles.

Hope you understand.
Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

tokumaru wrote:I don't know if you know that Celius, but when the screen scrolls, you only draw what is new, in the form or rows and columns.
I understand that, I believe I was translating it into my head incorrectly. I'm retarded, I thought people were talking about meta tiles for some reason. Like, for a one screen 16x15 map using 2x2 meta tiles, you had to have all 1024 bytes for each tile, instead of one byte for each 2x2 meta tile. Like decompressed meta tiles. I don't know. But what do you think would be a good way to do what you were talking about?

I think I'll try a few things, I should be able to come up with something. I'd be able to have about 64 maps + code in 1 16k PRG bank. So 1 8x8 screen grid in 1 bank, that's pretty good actually. And I don't know why people keep saying 2x2 meta tiles makes a 16x16 map, it doesn't. It makes a 16x15. I've counted. I only need $F0 bytes to fill a whole screen. Now that I think about it, I don't think it'll be THAT much space taken up.

So pretty much I'm just retarded. I think reading the columns will be the hardest part. Should I have the whole 8x8 screen grid is 1 big 1 dimensional array? Or should I have 64 seperate screens? I think the big array will be the better option, because reading columns will be alot easier. Thanks a bunch for your feedback. =)
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

tokumaru wrote:1. object-based levels, where every screen starts empty and is filled with objects at specifyed positions, in RAM;
I don't think this one is very good, at least not for an RPG. While space-efficient, it would be very limited and glitchy if you happen to superpose one object on another.
2. grid-based with compression, where you decompress the screens to RAM as the player moves;
This is probably the best option for a RPG or a strategy game.
3. grid-based with heavier indirection, as in the Sonic series, where you have more than 1 level of metatiles.
This will be better for platformers or shooters, where maps are larger and less detailed than with RPGs.

For my current game (that is a action-adventure game) I use two levels of metatiles. I use maps of 8x6 blocks that are 32x32 pixels (the maps are compressed with a kind of RLE), then I use 16x16 metatiles (there is 4 of them in a 32x32 block) that contain tile graphics and collision properties. This works fine because it is an action-RPG so it needs less detail than a true RPG. However, in a real RPG you couldn't use that method because you need a lot of detail with houses, chests, etc...
I hope I was clear enough.
Celius, I definitely should make an univeral RPG map library available for anyone that want to make a 16x16 based RPG. I'd do that someday, but I have pretty much alot of work right now.
Useless, lumbering half-wits don't scare us.
Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

I am thinking of making a NES ROM map editor like the one I made, but for large 8x8 screen maps. But the bad thing is that it'd only be able to let you edit a 4x8 section, because RAM is only 8k, and 8x8 screens is 16k. So this is not good. I don't know how I could do this. I really wish I could have 1 big map. Oh, I still could, I'd just have to edit it like 4 screens verticly, and 8 screens horizontally. Then I'll just copy/paste the data from one, and combine it as the second half of the other. I don't know. I cannot make any C/C++ programs, that is out of the question. I will learn those sometime, but not soon.
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

Metatile maps are smaller and will also probably compress better in some cases than 8x8 grid maps. I don't think it's any harder to index metatiles (just run through each row/column twice, drawing half on each pass).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Celius, here is a quick tip to draw (to the name tables) metatiles in the form of rows or columns of tiles:

Have the maps for the metatiles arranged in a non-sequential way. Reserve 4 pages (256 bytes) of ROM, so that one page represents the top left tile, the other page represents the top right tile, and so on. Then you can have access to any tile of the metatile just indexing with the metatile number.

Then to draw a row of tiles, say, the top half of the metatiles, you'd do it like this:

Code: Select all

LDA (screenmap), Y 'load the metatile index
TAY 'put it in Y
LDA upleft, Y 'load upper left tile index
STA $2007 'write it
LDA upright, Y 'load upper right tile index
STA $2007 'write it
Then you move to the next metatile.

It will work you have maps for your metatiles, but I just remembered that you were using a format where you specified the index of the first tile the other 3 were the ones following the first, right?

You can still draw a row just as easily. Like the previous example, say you want to draw the top half of the metatiles:

Code: Select all

LDA (screenmap), Y 'load the metatile index
TAY 'put it in Y
STY $2007 'write the index of the top left tile
INY 'make it the index of the top right tile
STY $2007 'write it
Or something like this. Hope you got the idea.
Celius
Posts: 2158
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

I'm sorry, I'm not calling you a bad explainer, but I dont' know what you mean. My format does this:

meta tile index = $82

This is what will appear on screen:

$82,$83
$92,$93

If the variable Tile_Index is $82, and is processesed through my subroutine, then that is what will happen. It will show up as what I posted above. But why do you only show me like 3 writes to $2007? I don't know how this shows a column, or a row. Would you care to explain again? I don't get what you are saying when you are talking about the upper right/left corners. Sorry...
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Celius wrote:If the variable Tile_Index is $82, and is processesed through my subroutine, then that is what will happen.
Where? In your level editor? You'll probably have to write faster code for the game itself. I'd suggest you have metatile $82 be composed by tiles $82, $83, $84 and $85 just for simplicity. You can write faster code if you do it like this. You must be doing it the way you do so that you can easily view the blocks when you use a pattern table viewer, right? Please don't bother with that if it will slow down your code.
But why do you only show me like 3 writes to $2007?
Because I showed you how to render 1 metatile only. It is up to you to build the rendering code around that. I don't know if you're gonna make a loop, or have it unrolled... so I showed you how to render only 1, and you repeat that as you'd like.
I don't get what you are saying when you are talking about the upper right/left corners.
Your metatile is composed by 4 tiles: the upper left one (0), the upper right one (1), the lower left one (2) and the lower right one (3). Like this:

Code: Select all

0 1
2 3
When you're copying rows of tiles to the name tables, you have PPU increments set to 1, then you'll be drawing either tiles 0 and 1 or 2 and 3. Remember, rows. If you're rendering columns, with PPU increments set to 32, you'll be drawing either tiles 0 and 2 or tiles 1 and 3.

The code I showed you before wrote tile 0 and then tile 1. You'll have to build the other 3 versions of that, or figure out a way to use the same routine for all 4 cases.

Anyway, you'll be running through all the metatiles in the row and/or column to be drawn, writing the 2 tiles of it that interest you, depending on whether you're drawing a row or a column, and if it's the first or second half of it.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

tokumaru wrote:
Celius wrote:If the variable Tile_Index is $82, and is processesed through my subroutine, then that is what will happen.
Where? In your level editor? You'll probably have to write faster code for the game itself. I'd suggest you have metatile $82 be composed by tiles $82, $83, $84 and $85 just for simplicity.
I'd suggest
$84 $86
$85 $87
which would let you use the same tile data for backgrounds and 8x16 sprites. However, if you don't run your metatiles through a lookup table, you're going to have problems with solid-color sky metatiles taking up 4 tiles in your pattern table instead of 1.
You can write faster code if you do it like this. You must be doing it the way you do so that you can easily view the blocks when you use a pattern table viewer, right? Please don't bother with that if it will slow down your code.
If you have a pattern table viewer or editor that supports 8x16 sprites, such as the tile view of 8TED, then the layout I proposed will still look fine.
Post Reply